#pragma once
#include "../common/dispatcher.hpp"
#include "rpc_registry.hpp"
#include "rpc_router.hpp"
#include "rpc_topic.hpp"
#include "../client/rpc_client.hpp"
#include <memory>

namespace rpc
{
    namespace server
    {
        //注册中心服务端，只需要针对服务发现与请求进行处理
        class RegistyServer
        {
        public:
            using ptr = std::shared_ptr<RegistyServer>;
            RegistyServer(int port):_pd_manager(std::make_shared<PDManager>()),
                _dispatcher(std::make_shared<DisPatcher>())
            {
                auto server_cb = std::bind(&PDManager::onServerRequest, _pd_manager.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, server_cb);

                _server = ServerFactory::create(port);

                auto message_cb = std::bind(&DisPatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);

                auto close_cb = std::bind(&RegistyServer::onConnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }
            void start()
            {
                _server->start();
            }
        private:
            void onConnShutdown(const BaseConnection::ptr &conn)
            {   
                return _pd_manager->onConnShutdown(conn);
            }
        private:
            PDManager::ptr _pd_manager;
            DisPatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;
            //rpc-server端有两套地址信息
            //1. rpc服务端地址信息：必须是rpc服务器对外访问地址
            //2. 注册中心服务端地址信息：启用服务注册后，连接注册中心进行服务注册所使用
            RpcServer(const Address& access_addr, const Address& server_addr = Address(), bool enableRegistry = false):
                _enableRegistry(enableRegistry),
                _access_addr(access_addr),
                _router(std::make_shared<RpcRouter>()),
                _dispatcher(std::make_shared<DisPatcher>())
            {
                if(_enableRegistry)
                {
                    _reg_client = std::make_shared<client::RegistryClient>(server_addr.first, server_addr.second);
                }

                //当前成员server是提供rpc服务的
                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<RpcRequest>(MType::REQ_RPC, rpc_cb);

                _server = ServerFactory::create(access_addr.second);
                auto message_cb = std::bind(&DisPatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
            }
            void registerMethod(const ServiceDescribe::ptr &service)
            {
                if(_enableRegistry)
                {
                    _reg_client->registryMethod(service->method(), _access_addr);
                }
                _router->registerMethod(service);
            }
            void start()
            {
                _server->start();
            }
        private:
            bool _enableRegistry;
            Address _access_addr;
            client::RegistryClient::ptr _reg_client;
            RpcRouter::ptr _router;
            DisPatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };

        class TopicServer
        {
        public:
            using ptr = std::shared_ptr<TopicServer>;
            TopicServer(int port):_topic_manager(std::make_shared<TopicManager>()),
                _dispatcher(std::make_shared<DisPatcher>())
            {
                auto server_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<TopicRequest>(MType::REQ_TOPIC, server_cb);

                _server = ServerFactory::create(port);

                auto message_cb = std::bind(&DisPatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);

                auto close_cb = std::bind(&TopicServer::onShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }
            void start()
            {
                _server->start();
            }
        private:
            void onShutdown(const BaseConnection::ptr &conn)
            {   
                return _topic_manager->onShutdown(conn);
            }
        private:
            TopicManager::ptr _topic_manager;
            DisPatcher::ptr _dispatcher;
            BaseServer::ptr _server;
        };
    }
}